package ar.com.grupo1.ler.dominio;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import ar.com.grupo1.ler.exceptions.ValoresInvalidosException;

/**
 * Reune el comportamiento que debe tener todo vehiculo
 * 
 */
public abstract class Vehiculo {

	private static Logger logger = Logger.getLogger(Vehiculo.class);
	public static BigDecimal COSTO_FIJO_MENSUAL = new BigDecimal("317.40");
	public static BigDecimal VALOR_LITRO_COMBUSTIBLE = new BigDecimal("2.03");

	private List<Viaje> viajes = new ArrayList<Viaje>();
	private Long litrosEnTanque = new Long(0);
	private Conductor conductor;

	public List<Viaje> getViajes() {
		return viajes;
	}

	public void setViajes(List<Viaje> viajes) {
		this.viajes = viajes;
	}

	public void addViaje(Viaje viaje) {
		this.viajes.add(viaje);
	}

	public Conductor getConductor() {
		return conductor;
	}

	public void setConductor(Conductor conductor) {
		this.conductor = conductor;
	}

	/**
	 * Determina si el vehiculo tiene el combustible necesario para realizar un
	 * viaje
	 * 
	 * @param viaje
	 * @return
	 * @throws ValoresInvalidosException
	 */
	public boolean hasCombustibleNecesario(Viaje viaje) throws ValoresInvalidosException {
		BigDecimal litros = new BigDecimal(litrosEnTanque);
		BigDecimal consumoCombustible = getConsumoCombustible(viaje);
		BigDecimal resultado = litros.subtract(consumoCombustible);
		logger.debug("El resultado de restar litrosEnTanque: " + litrosEnTanque + " y consumoCombustible: " + consumoCombustible
				+ " es " + resultado);
		return resultado.doubleValue() >= 0;
	}

	public Long getLitrosEnTanque() {
		return litrosEnTanque;
	}

	public void setLitrosEnTanque(Long litrosEnTanque) {
		this.litrosEnTanque = litrosEnTanque;
	}

	/**
	 * Calcula el consumo de combustible que tuvo de todos los viajes asignados
	 * de un vehiculo
	 * 
	 * @return
	 * @throws ValoresInvalidosException
	 */
	public BigDecimal getConsumoTotal() throws ValoresInvalidosException {
		BigDecimal consumoTotal = new BigDecimal("0");
		if (viajes != null) {
			for (Viaje viaje : viajes) {
				consumoTotal = consumoTotal.add(getConsumoCombustible(viaje));
			}
		} else {
			logger.info("No existen viajes asignados");
		}
		return consumoTotal;
	}

	/**
	 * Obtiene la carga Maxima soportada por el vehiculo
	 * 
	 * @return
	 */
	public abstract Long getCargaMaxima();

	/**
	 * Calcula el tiempo de viaje de un vehiculo (se expresa en horas)
	 * 
	 * Obtiene cuanto se demora al realizar un viaje
	 * 
	 * @param viaje
	 * @return
	 * @throws ValoresInvalidosException
	 */
	public abstract BigDecimal getTiempoViaje(Viaje viaje) throws ValoresInvalidosException;

	/**
	 * Obtiene cuanto se consume al realizar un viaje
	 * 
	 * @param viaje
	 * @return
	 * @throws ValoresInvalidosException
	 */
	public abstract BigDecimal getConsumoCombustible(Viaje viaje) throws ValoresInvalidosException;

	/**
	 * Verifica que el vehiculo este disponible para viajar
	 * 
	 * @param viaje
	 * @return
	 * @throws ValoresInvalidosException
	 */
	public boolean isDisponible(Viaje viaje) throws ValoresInvalidosException {
		boolean soportaCarga = getCargaMaxima() >= viaje.getCarga();
		boolean llegaATiempo = getTiempoViaje(viaje).compareTo(new BigDecimal(viaje.getTiempoMaximo())) <= 0;
		boolean llegaConElCombustible = hasCombustibleNecesario(viaje);
		logger.debug("\nSoporta Carga es " + soportaCarga + "\nLlega A Tiempo es " + llegaATiempo
				+ "\nLlega Con El Combustible es " + llegaConElCombustible + ".\nDatos del viaje: " + viaje);
		return soportaCarga && llegaATiempo && llegaConElCombustible;
	}

	/**
	 * Determina el gasto del vehiculo
	 * 
	 * @return
	 * @throws ValoresInvalidosException
	 */
	public BigDecimal getGasto() throws ValoresInvalidosException {
		BigDecimal gasto = new BigDecimal("0");

		BigDecimal gastoCombustible = getConsumoTotal().multiply(VALOR_LITRO_COMBUSTIBLE);
		gasto = gasto.add(gastoCombustible);

		BigDecimal gastoSueldo = conductor != null ? conductor.getSueldo() : new BigDecimal("0");
		gasto = gasto.add(gastoSueldo);

		gasto = gasto.add(COSTO_FIJO_MENSUAL);

		logger.debug("Gasto del vehiculo es " + gasto + ". Gasto por Combustible es " + gastoCombustible
				+ ". El COSTO FIJO MENSUAL es " + COSTO_FIJO_MENSUAL + ". El Sueldo es " + gastoSueldo);
		return gasto;
	}
}
